BUILD_DIR = ./build
BOCHS_DIR = /usr/local/bochs
BOCHSRC = ./boot/bochsrc.disk
HD60 = ./boot/hd60M.img
HD80 = ./boot/hd80M.img
ENTRY_POINT = 0xc0001500
AS = nasm
CC = gcc
LD = ld
LIB = -I lib/ -I lib/user/ -I lib/kernel -I device/ -I kernel/ -I thread/ -I userprog/ -I fs/ -I shell/
ASFLAGS = -f elf32
CFLAGS = -m32 -Wall $(LIB) -c -fno-builtin -W -Wstrict-prototypes -Wmissing-prototypes -fno-stack-protector
LDFLAGS = -m elf_i386 -Ttext $(ENTRY_POINT) -e main -Map $(BUILD_DIR)/kernel.map
OBJS = $(BUILD_DIR)/main.o $(BUILD_DIR)/init.o $(BUILD_DIR)/interrupt.o \
	$(BUILD_DIR)/timer.o $(BUILD_DIR)/kernel.o $(BUILD_DIR)/print.o \
	$(BUILD_DIR)/debug.o $(BUILD_DIR)/memory.o $(BUILD_DIR)/bitmap.o \
	$(BUILD_DIR)/string.o $(BUILD_DIR)/thread.o $(BUILD_DIR)/list.o \
	$(BUILD_DIR)/switch.o $(BUILD_DIR)/sync.o $(BUILD_DIR)/console.o \
	$(BUILD_DIR)/keyboard.o $(BUILD_DIR)/ioqueue.o $(BUILD_DIR)/tss.o \
	$(BUILD_DIR)/process.o $(BUILD_DIR)/syscall.o $(BUILD_DIR)/syscall-init.o \
	$(BUILD_DIR)/stdio.o $(BUILD_DIR)/stdio-kernel.o $(BUILD_DIR)/ide.o \
	$(BUILD_DIR)/fs.o $(BUILD_DIR)/inode.o $(BUILD_DIR)/file.o \
	$(BUILD_DIR)/dir.o $(BUILD_DIR)/fork.o $(BUILD_DIR)/assert.o \
	$(BUILD_DIR)/shell.o $(BUILD_DIR)/buildin_cmd.o $(BUILD_DIR)/exec.o
BOOT = $(BUILD_DIR)/mbr.bin $(BUILD_DIR)/loader.bin 

all: bochs mk_dir build hd


################# C代码编译 #################
$(BUILD_DIR)/main.o: kernel/main.c \
	lib/kernel/print.h lib/stdint.h kernel/init.h \
	thread/thread.h kernel/memory.h kernel/interrupt.h \
	kernel/debug.h userprog/process.h lib/user/syscall.h \
	userprog/syscall-init.h lib/stdio.h fs/fs.h
	@echo "\033[33m Compiling ... \033[0m"
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/init.o: kernel/init.c kernel/init.h \
	kernel/interrupt.h lib/stdint.h kernel/interrupt.h device/timer.h \
	kernel/memory.h thread/thread.h device/console.h device/keyboard.h \
	userprog/tss.h userprog/syscall-init.h device/ide.h fs/fs.h
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/interrupt.o: kernel/interrupt.c kernel/interrupt.h \
	lib/stdint.h kernel/global.h lib/kernel/io.h lib/kernel/print.h
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/timer.o: device/timer.c device/timer.h \
	lib/stdint.h lib/kernel/io.h lib/kernel/print.h \
	thread/thread.h kernel/debug.h
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/debug.o: kernel/debug.c kernel/debug.h \
	lib/kernel/print.h lib/stdint.h kernel/interrupt.h
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/string.o: lib/string.c lib/string.h \
	kernel/global.h kernel/debug.h
	$(CC) $(CFLAGS) $< -o $@
 
$(BUILD_DIR)/bitmap.o: lib/kernel/bitmap.c lib/kernel/bitmap.h \
	kernel/debug.h kernel/interrupt.h lib/stdint.h
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/memory.o: kernel/memory.c kernel/memory.h \
	lib/stdint.h lib/kernel/print.h lib/kernel/bitmap.h lib/string.h \
	lib/kernel/list.h kernel/interrupt.h
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/thread.o: thread/thread.c thread/thread.h \
	lib/stdint.h lib/string.h kernel/memory.h kernel/global.h \
	lib/kernel/list.h kernel/debug.h kernel/interrupt.h \
	lib/kernel/print.h userprog/process.h thread/sync.h fs/file.h
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/list.o: lib/kernel/list.c lib/kernel/list.h \
	lib/stdint.h kernel/global.h kernel/interrupt.h
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/sync.o: thread/sync.c thread/sync.h \
	lib/stdint.h thread/thread.h kernel/interrupt.h \
	kernel/debug.h
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/console.o: device/console.c device/console.h \
	lib/stdint.h lib/kernel/print.h thread/sync.h thread/thread.h
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/keyboard.o: device/keyboard.c device/keyboard.h \
	kernel/global.h lib/kernel/print.h kernel/interrupt.h lib/kernel/io.h \
	device/ioqueue.h
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/ioqueue.o: device/ioqueue.c device/ioqueue.h \
	kernel/global.h lib/stdint.h thread/thread.h thread/sync.h \
	kernel/debug.h kernel/interrupt.h
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/tss.o: userprog/tss.c userprog/tss.h \
	kernel/global.h thread/thread.h lib/kernel/print.h lib/string.h
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/process.o: userprog/process.c userprog/process.h \
	kernel/global.h thread/thread.h lib/string.h kernel/interrupt.h \
	userprog/tss.h kernel/debug.h device/console.h kernel/memory.h
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/syscall.o: lib/user/syscall.c lib/user/syscall.h \
	lib/stdint.h fs/fs.h
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/syscall-init.o: userprog/syscall-init.c userprog/syscall-init.h \
	lib/user/syscall.h kernel/global.h thread/thread.h lib/kernel/print.h \
	lib/string.h device/console.h fs/fs.h userprog/fork.h 
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/stdio.o: lib/stdio.c lib/stdio.h \
	lib/string.h kernel/global.h lib/user/syscall.h
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/stdio-kernel.o: lib/kernel/stdio-kernel.c lib/kernel/stdio-kernel.h \
	lib/stdint.h lib/stdio.h
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/ide.o: device/ide.c device/ide.h \
	kernel/global.h thread/sync.h lib/kernel/io.h lib/stdio.h lib/kernel/stdio-kernel.h \
	kernel/interrupt.h kernel/memory.h kernel/debug.h device/console.h device/timer.h \
	lib/string.h lib/kernel/list.h fs/super_block.h 
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/fs.o: fs/fs.c fs/fs.h fs/super_block.h fs/inode.h fs/dir.h \
	lib/stdint.h lib/kernel/stdio-kernel.h lib/kernel/list.h lib/string.h \
	device/ide.h kernel/global.h kernel/debug.h kernel/memory.h fs/file.h \
	device/console.h 
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/inode.o: fs/inode.c fs/inode.h device/ide.h kernel/global.h \
	lib/kernel/list.h kernel/debug.h lib/string.h kernel/interrupt.h thread/thread.h \
	kernel/memory.h fs/file.h fs/fs.h
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/file.o: fs/file.c fs/file.h fs/fs.h fs/inode.h device/ide.h \
	lib/kernel/stdio-kernel.h thread/thread.h lib/kernel/bitmap.h kernel/global.h \
	kernel/interrupt.h kernel/debug.h
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/dir.o: fs/dir.c fs/dir.h kernel/memory.h lib/kernel/stdio-kernel.h \
	fs/fs.h lib/string.h kernel/debug.h fs/file.h fs/inode.h device/ide.h \
	kernel/global.h lib/stdint.h 
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/fork.o: userprog/fork.c userprog/fork.h kernel/global.h \
	thread/thread.h kernel/interrupt.h kernel/debug.h fs/file.h \
	lib/string.h userprog/process.h
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/assert.o: lib/user/assert.c lib/user/assert.h lib/stdio.h
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/shell.o: shell/shell.c shell/shell.h \
	lib/user/assert.h kernel/global.h fs/file.h lib/user/syscall.h \
	lib/stdio.h lib/string.h lib/user/assert.h shell/buildin_cmd.h \
	userprog/exec.h
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/buildin_cmd.o: shell/buildin_cmd.c shell/buildin_cmd.h \
	kernel/global.h lib/user/syscall.h lib/stdio.h lib/stdint.h \
	fs/fs.h fs/dir.h shell/shell.h lib/user/assert.h
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/exec.o: userprog/exec.c userprog/exec.h thread/thread.h \
	lib/kernel/stdio-kernel.h fs/fs.h lib/string.h kernel/global.h \
	kernel/memory.h lib/stdint.h 
	$(CC) $(CFLAGS) $< -o $@

################# 汇编编译 #################
$(BUILD_DIR)/loader.bin: boot/loader.S
	$(AS) -I boot/include/ $< -o $@ 
$(BUILD_DIR)/mbr.bin: boot/mbr.S
	$(AS) -I boot/include/ $< -o $@ 
$(BUILD_DIR)/kernel.o: kernel/kernel.S
	$(AS) $(ASFLAGS) $< -o $@
$(BUILD_DIR)/print.o: lib/kernel/print.S
	$(AS) $(ASFLAGS) $< -o $@
$(BUILD_DIR)/switch.o: thread/switch.S
	$(AS) $(ASFLAGS) $< -o $@

################# 链接 #################
$(BUILD_DIR)/kernel.bin: $(OBJS) $(BOOT)
	@echo "\033[33m Linking ... \033[0m"
	$(LD) $(LDFLAGS) $(OBJS) -o $@

.PHONY: mk_dir hd clean all bochs rebuild _copyhd2bochshd updatehd backuphd newhd

bochs:
	@echo "\033[33m Copying $(BOCHSRC) to $(BOCHS_DIR)/$(notdir  $(BOCHSRC))... \033[0m"
	sudo cp -f $(BOCHSRC) $(BOCHS_DIR)/
	
# @echo "\033[33m Deleting $(BOCHS_DIR)/hd60M.img... \033[0m"
# sudo rm $(BOCHS_DIR)/hd60M.img
# @echo "\033[33m Creating $(BOCHS_DIR)/hd60M.img... \033[0m"
# sudo $(BOCHS_DIR)/bin/bximage -hd -mode="flat" -size=60 -q $(BOCHS_DIR)/hd60M.img
	if [ -e run.sh ] ;then\
		sudo rm run.sh;\
	fi
	touch run.sh 
	echo "cd $(BOCHS_DIR) && sudo bin/bochs -f $(notdir  $(BOCHSRC))" >run.sh

mk_dir:
	@echo "\033[33m Making Directory $(BUILD_DIR)/... \033[0m"
	if [ ! -d $(BUILD_DIR) ] ;then mkdir $(BUILD_DIR);fi

hd:
	@echo "\033[33m Writing to disk... \033[0m"
	sudo dd if=$(BUILD_DIR)/mbr.bin of=$(BOCHS_DIR)/hd60M.img bs=512 count=1 conv=notrunc
	sudo dd if=$(BUILD_DIR)/loader.bin of=$(BOCHS_DIR)/hd60M.img bs=512 count=4 seek=2 conv=notrunc
	sudo dd if=$(BUILD_DIR)/kernel.bin of=$(BOCHS_DIR)/hd60M.img bs=512 count=500 seek=9 conv=notrunc

clean:
	@echo "\033[33m Cleaning build files ... \033[0m"
	sudo rm -rf $(BUILD_DIR)

build: $(BUILD_DIR)/kernel.bin

_copyhd2bochshd:
	@echo "\033[33m Copying $(HD60) to $(BOCHS_DIR)/$(notdir  $(HD60))... \033[0m"
	sudo cp -f $(HD60) $(BOCHS_DIR)/
	@echo "\033[33m Copying $(HD80) to $(BOCHS_DIR)/$(notdir  $(HD80))... \033[0m"
	sudo cp -f $(HD80) $(BOCHS_DIR)/

updatehd: _copyhd2bochshd hd # 将工程目录下的硬盘复制到bochs根目录下

backuphd: # 将bochs目录下被操作过的硬盘覆盖工程目录下的硬盘备份
	@echo "\033[33m BackUp hd ... \033[0m"
	@echo "\033[33m Copying $(BOCHS_DIR)/$(notdir  $(HD60)) to $(HD60) ... \033[0m"
	sudo cp -f $(BOCHS_DIR)/$(notdir  $(HD60)) ./boot/
	@echo "\033[33m Copying $(BOCHS_DIR)/$(notdir  $(HD80)) to $(HD80)... \033[0m"
	sudo cp -f $(BOCHS_DIR)/$(notdir  $(HD80)) ./boot/

newhd:
	@echo "\033[33m Creating New hd to $(BOCHS_DIR) ... \033[0m"
	sudo cp -f ./boot/newhd/hd60M.img $(BOCHS_DIR)
	sudo cp -f ./boot/newhd/hd80M.img $(BOCHS_DIR)

rebuild: clean all

